/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package testing;

import com.thesis.VeloEstiCellID.VeloEstiCellID;
import com.thesis.algorithm.Device;
import com.thesis.algorithm.FileConverter;
import com.thesis.algorithm.Sequence;
import com.thesis.algorithm.SequenceElement;
import com.thesis.utils.CONSTANTS;
import com.thesis.utils.VelocityEstimateTest;
import java.io.IOException;
import java.io.Writer;
import java.util.LinkedList;
import java.util.Random;

/**
 *
 * @author Aya Hikaru
 */
class VeloEstiCellIDWrapper {

    VeloEstiCellID vecid = null;
    LinkedList<Sequence> _TRAINDATA = null;
    LinkedList<Sequence> _TESTDATA = null;
    LinkedList<VelocityEstimateTest> vets = null;

    public VeloEstiCellIDWrapper() {
        FileConverter fc = new FileConverter(CONSTANTS.TRAIN_DATA_FOLDER);
        FileConverter fctest = new FileConverter(CONSTANTS.TEST_DATA_FOLDER);
        this.vecid = new VeloEstiCellID(fc.listOfDevices);
        _TRAINDATA = this.vecid.allCellIDSeq;
        vets = new LinkedList<VelocityEstimateTest>();
        VelocityEstimateTest tmpvet;
        for (int i = 0; i < fc.listOfDevices.size(); i++) {
            Device d = fc.listOfDevices.get(i);
            tmpvet = new VelocityEstimateTest(d);
            vets.add(tmpvet);
        }
        _TESTDATA = VeloEstiCellID.produceTestSequence(fctest.listOfDevices);
        
    }

    public void testSequenceAndPrintToFile(int sequence_length, int consideredtime, Writer outSequence, Writer outExcel) throws IOException {

        Random randomGenerator = new Random();
        int count = 0;
        double SumDiff = 0;
        double SumDiffLT0 = 0;
        double SumDiffST0 = 0;
        int countLT0 = 0;
        int countST0 = 0;
        double MaxLT0 = 0;
        double MinLT0 = 5000;
        double MaxST0 = -5000;
        double MinST0 = 0;
        double tmp = 0;
        double Max = 0;
        double Min = 5000;
        double estiVelo = 0;
        double GPSv = 0;
        int countzerocase = 0;
        int countST5 = 0;

        outExcel.write("estiVelo\tGPSv\tMath.abs(GPSv-estiVelo)\tGPSv-estiVelo\n");
        for (int i = 0; i < CONSTANTS.nExample; i++) {
            // test data
            if (_TESTDATA.size() == 0) {
                System.err.println("_TESTDATA size = 0");
                return;
            }
            int fileindex = randomGenerator.nextInt(_TESTDATA.size() - 1);
            int start = randomGenerator.nextInt(_TESTDATA.get(fileindex).size() - 1);
            Sequence testdata = new Sequence();
            int totalsequencelength = sequence_length;
            for (int j = start; j < _TESTDATA.get(fileindex).size(); j++) {
                testdata.add(new SequenceElement(_TESTDATA.get(fileindex)
                        .get(j)));
                if (totalsequencelength >= (int) (testdata.getLast().Repetition)) {
                    totalsequencelength -= testdata.getLast().Repetition;
                } else {
                    testdata.getLast().Repetition = (char) (totalsequencelength);
                    totalsequencelength = 0;
                }
                if (totalsequencelength == 0) {
                    break;
                }
            }
            int consideredSequencelength = consideredtime;
            int j = 0;
            for (j = testdata.size() - 1; j >= 0; j--) {
                if (consideredSequencelength >= (int) (testdata.get(j).Repetition)) {
                    consideredSequencelength -= testdata.get(j).Repetition;
                } else {
                    testdata.get(j).Repetition = (char) (consideredSequencelength);
                    consideredSequencelength = 0;
                }
                if (consideredSequencelength == 0) {
                    break;
                }
            }
            for (int k = j; k > 0; k--)
            {
                testdata.sequenceinFile.removeFirst();
            }
            testdata.BusRouteID = _TESTDATA.get(fileindex).BusRouteID;
            System.out.println("TEST " + i);
            outSequence.write("TEST: " + i + "\n");
            outSequence.write("BUSROUTE: " + testdata.BusRouteID + " from " + start + "\n");
            outSequence.write("TEST DATA " + testdata.toString() + "\n");
            //++++++++++++++ HUNG MATCH testdata voi _TRAINDATA RUI RETURN CHO THO CAI FILE INDEX VOI STARTV AND ENDV++++

//            estiVelo = vecid.returnVelocityTimeInterval(fileindex, startV, endV, testdata.score()) * 3600;
            
            int[] result = vecid.match(testdata, outSequence);
            
            //estiVelo = vecid.returnVelocityTimeInterval(fileindex, startV, endV, testdata.score()) * 3600;
            
            
            
            //++++++++++++++ dong estiVelo o tren la test thui, dong duoi nay moi la tinh dua tren testdata time interval thiet
//            outSequence.write("matching result - index: " + result[0]+"\n");
//            outSequence.write("matching result - start: " + result[1]+"\n");
//            outSequence.write("matching result - end  : " + result[2]+"\n");
            estiVelo = vecid.returnDistanceTimeInterval(result[0], result[1], result[2], testdata.getFirst().Repetition, testdata.getLast().Repetition) * 3600 / testdata.score();
            int startV = _TRAINDATA.get(result[0]).scorebefore(result[1]);
            int endV = _TRAINDATA.get(result[0]).scorebefore(result[2]);
            if (testdata.getFirst().Repetition < _TRAINDATA.get(result[0]).get(result[1]).Repetition)
                startV += (_TRAINDATA.get(result[0]).get(result[1]).Repetition - testdata.getFirst().Repetition);
            if (testdata.getLast().Repetition >= _TRAINDATA.get(result[0]).get(result[2]).Repetition)
                endV += _TRAINDATA.get(result[0]).get(result[2]).Repetition;
            else
                endV += testdata.getLast().Repetition;
            
            int beforescore = _TESTDATA.get(fileindex).scorebefore(start) + (sequence_length - consideredtime);
            GPSv = vets.get(fileindex).returnVelocity(beforescore, beforescore + consideredtime) * 3600;
            outSequence.write("matched: index: " + result[0] + " busNo: " + _TRAINDATA.get(result[0]).BusRouteID + "startV: " + startV
                    + " endV: " + endV + "\n");
            outSequence.write("real: index: " + fileindex + " busNo: " + _TESTDATA.get(fileindex).BusRouteID + "start: " + beforescore + " end: " + (beforescore + consideredtime) + "\n");
            outSequence.write("EstiVelo: " + estiVelo + "\n");
            outSequence.write("GPSv: " + GPSv + "\n\n\n");
            tmp = GPSv - estiVelo;
            outExcel.write(estiVelo + "\t" + GPSv + "\t" + Math.abs(tmp) + "\t" + tmp + "\n");
            if (estiVelo > 0.000001 && GPSv > 0.000001) {
                SumDiff += Math.abs(tmp);
                count++;
                if (Math.abs(tmp) < 5) {
                    countST5++;
                }
                if (Math.abs(tmp) > Max) {
                    Max = Math.abs(tmp);
                }
                if (Math.abs(tmp) < Min) {
                    Min = Math.abs(tmp);
                }
                if (tmp > 0) {
                    countLT0++;
                    SumDiffLT0 += tmp;
                    if (tmp > MaxLT0) {
                        MaxLT0 = tmp;
                    }
                    if (tmp < MinLT0) {
                        MinLT0 = tmp;
                    }
                } else if (tmp < 0) {
                    countST0++;
                    SumDiffST0 += tmp;
                    if (tmp > MaxST0) {
                        MaxST0 = tmp;
                    }
                    if (tmp < MinST0) {
                        MinST0 = tmp;
                    }
                }
            } else {
                countzerocase++;
            }
        }
        outExcel.write("MIN:\t" + Min + "\n");
        outExcel.write("MAX:\t" + Max + "\n");
        outExcel.write("AVG:\t" + (SumDiff / count) + "\n");
        outExcel.write("COUNT:\t" + count + "\n");
        outExcel.write("COUNTZEROCASE:\t" + (countzerocase * 100.0 / count) + "%\n");
        outExcel.write("MINLT0:\t" + MinLT0 + "\n");
        outExcel.write("MAXLT0:\t" + MaxLT0 + "\n");
        outExcel.write("AVGLT0:\t" + (SumDiffLT0 / countLT0) + "\n");
        outExcel.write("COUNTLT0:\t" + (countLT0 * 100.0 / count) + "%\n");
        outExcel.write("MINST0:\t" + MinST0 + "\n");
        outExcel.write("MAXST0:\t" + MaxST0 + "\n");
        outExcel.write("AVGST0:\t" + (SumDiffST0 / countST0) + "\n");
        outExcel.write("COUNTST0:\t" + (countST0 * 100.0 / count) + "%\n");
        outExcel.write("COUNTST5:\t" + (100.0 * countST5 / count) + "%\n");
        outExcel.close();
        outSequence.close();
    }
}